<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>websocket会话</title>
    <link type="text/css" rel="stylesheet" href="css/socket.css" th:href="@{/css/socket.css}">
</head>
<body>
监控列表<br/>
<div id="message"></div>
<div>
    <input id="xm" type="text" th:placeholder="匿名用户" th:label="姓名" value="">
    <input id="content" type="text" value="">
    <button type="button" id="send">发送</button>
</div>
<div>
    <button type="button" id="down">下线</button>
    <button type="button" id="up">上线</button>
</div>
</body>
<script src="https://libs.baidu.com/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript">
    console.log("====这个是判断浏览器的兼容性-===" + window.WebSocket + "++++++++++" + window.MozWebSocket);
    var send = document.getElementById("send");
    var down = document.getElementById("down");
    var up = document.getElementById("up");
    var content = document.getElementById("content");
    var xm = document.getElementById("xm");//这里以前用的名称 var name 然后name.value 获取不到值。不知为什么，可能是保留值问题

    //websocket实例
    var ws;
    //避免重复连接
    var lockReconnect = false;

    //用户昵称
    var nickName = "匿名用户";


    var ids = guid();
    //连接地址 document.location.host = window.location.host==ip:port
    // wsUrl = "ws://" + window.location.host + "/mysocket/" + ids;
    var urlStr = "[[${url}]]/";
    var wsUrl = urlStr + getName();

    send.onclick = function (ev) {
        ws.send(content.value);
    };

    down.onclick = function (ev) {
        closeWebscoket();
    };

    up.onclick = function (ev) {
        //这里上线就是新创建一个连接，如果没有断开，那么一个浏览器中会出现多个连接，那么出现的消息会是多条哦
        alert("看看就可以了！");
        return;
        createWebsocket(wsUrl);
    };

    xm.oninput = function (ev) {
        $.ajax({
            url:"/changeName",
            type:"post",
            data:{"name":getName(),"uuid":"[[${uuid}]]"},
            datatype:"json",
            success:function (data) {
              console.log(data)
            }
        });
    };

    //创建连接
    function createWebsocket(url) {
        console.log("创建ws对象。。。");
        if (!window.WebSocket) {
            window.WebSocket = window.MozWebSocket;
        }
        console.log(lockReconnect + "" + window.WebSocket );
        //'WebSocket' in window
        try {
            if (typeof WebSocket != 'undefined'&& !lockReconnect) {
                ws = new WebSocket(wsUrl);
                lockReconnect = true;
            } else {
                console.log('该浏览器不支持websocket!');
                return;
            }
            initEventHandle();
        } catch (e) {
            console.log("创建对象失败。。");
        }
    }

    //关闭连接
    function closeWebscoket() {
        //连接关闭那么就没有连接了，不是重复连接了
        lockReconnect = false;
        console.log("关闭连接");
        ws.close();
    }

    function initEventHandle() {
        ws.onopen = function () {
            sendMessageInnerHtml("开启连接");
            //检测心跳
            heartCheck.reset().start();
            //heartCheck1.start();
        };

        ws.onmessage = function (event) {
            var message = event.data;
            if ("pong" === message) {
                //如果收到消息，心跳检测重置
                //拿到任何消息都说明连接正常
                console.log(message)
            } else {
                sendMessageInnerHtml("收到的消息：" + message);
            }
            heartCheck.reset().start();
            //heartCheck1.start();
        };

        ws.onclose = function () {
            console.log("连接关闭，重新连接");
            //只要断开就会重连，那么就不是重复连接了
            lockReconnect = false;
            //reconnect(wsUrl);
            reconnect(urlStr + getName())
        };

        ws.onerror = function (e) {
            console.log('websocket 发生异常断开重新连接: ' + e.code + ' ' + e.reason + ' ' + e.wasClean);
            lockReconnect = false;
            reconnect(wsUrl);
        };
    }

    //页面消息更新
    function sendMessageInnerHtml(innerHtml) {
        var e = document.getElementById("message");
        e.innerHTML += innerHtml + "<br/>";
        //style{overflow:auto} 结合就可以滚屏一直在最后
        e.scrollTop = e.scrollHeight;
    }

    //获取当前用户名称
    function getName() {
        return xm.value === "" ? nickName : xm.value;
    }

    //重连接方法
    function reconnect(url) {
        sendMessageInnerHtml("正在重新连接。。。。");
        //如果当前连接连着了就不作为
        if (lockReconnect)
            return;
        //如果没有连接，现在开始连接，这里不清楚为什么要为true,创建成功为true不是很好嘛
        //lockReconnect = true;
        //没连接上会一直重新连接，设置延迟避免请求过多
        setTimeout(function () {
            createWebsocket(url);
            console.log("创建对象");
            lockReconnect = false;
        }, 2000);
    }

    //心跳检测
    var heartCheck1 = {
        timeout: 5000,
        timeoutObj: null,
        serverTimeoutObj: null,
        start: function () {
            //console.log('start heart');
            var self = this;
            this.timeoutObj && clearTimeout(this.timeoutObj);
            this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
            this.timeoutObj = setTimeout(function () {
                //发送测试信息，后端收到后，返回一个消息，
                ws.send('ping');
                self.serverTimeoutObj = setTimeout(function () {
                    ws.close();
                }, self.timeout);
            }, this.timeout)
        }
    };
    //心跳检测
    var heartCheck = {
        timeout: 6000,//超时6秒
        timeoutObj: null,
        serverTimeoutObj: null,
        reset: function () {
            console.log("收到消息，检测正常");
            //这里是清除定时，这个timeoutObj是心跳的定时
            clearTimeout(this.timeoutObj);
            clearTimeout(this.serverTimeoutObj);
            return this;
        },
        start: function () {
             var self = this;
            this.timeoutObj = setTimeout(function () {
                //这里发送一个心跳，后端接收到后返回一个消息
                //onmessage拿到心跳说明正常连接
                ws.send("ping");
                console.log("发送一个💗跳  HEART BEAT");

                self.serverTimeoutObj = setTimeout(function(){//如果超过一定时间还没重置，说明后端主动断开了
                     ws.close();     //如果onclose会执行reconnect，我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
                 }, self.timeout);

            }, this.timeout);
        }
    };

    // 监听窗口关闭事件，当窗口关闭时，主动去关闭websocket连接，防止连接还没断开就关闭窗口，server端会抛异常。
    window.onbeforeunload = function () {
        closeWebscoket();
    };

    /**
     *获取id
     */
    function guid() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
            var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        });
    }

    createWebsocket(wsUrl);
</script>
</html>
